package com.fractalist.base.core.utils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Bean工具
 * 
 * @author 李博
 * 
 */
public class BeanTools {
	/**
	 * bean数据同步 注:o和syno必须得是同一个bean
	 * 
	 * @param o
	 *            有数据的bean
	 * @param syno
	 *            需要同步的bean
	 * @return
	 */
	public static boolean beansync(Object o, Object syno) {

		return beansync(o, syno, new ArrayList<String>());
	}

	/**
	 * bean数据同步 注:o和syno必须得是同一个bean
	 * 
	 * @param o
	 *            有数据的bean
	 * @param syno
	 *            需要同步的bean
	 * @param excluded
	 *            不需要同步的属性
	 * @return
	 */
	public static boolean beansync(Object o, Object syno, List<String> excluded) {
		if (!o.getClass().toString().equals(syno.getClass().toString())) {
			return false;
		}

		try {
			PropertyDescriptor[] pdso = getPropertyDescriptor(o);
			PropertyDescriptor[] pdsn = getPropertyDescriptor(syno);

			String name = "";
			boolean cont = false;
			for (int i = 0; i < pdso.length; i++) {
				PropertyDescriptor pdo = pdso[i];
				PropertyDescriptor pdn = pdsn[i];
				name = pdo.getName();
				cont = false;

				for (int r = 0; r < excluded.size(); r++) {
					if (name.toUpperCase()
							.equals(excluded.get(r).toUpperCase())) {
						cont = true;
						break;
					}
				}
				if (name.equals("class") || cont) {
					continue;
				}

				Object tempo = getbeanvalue(pdn, syno);
				if (tempo == null) {
					Object add = getbeanvalue(pdo, o);
					if (add != null) {
						setbeanvalue(pdn, syno, add);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;

	}

	private static BeanInfo getBeanInfo(Object o) throws Exception {
		return Introspector.getBeanInfo(o.getClass());
	}

	private static PropertyDescriptor[] getPropertyDescriptor(Object o)
			throws Exception {

		return getPropertyDescriptor(getBeanInfo(o));

	}

	private static PropertyDescriptor[] getPropertyDescriptor(BeanInfo beaninfo) {
		return beaninfo.getPropertyDescriptors();
	}

	/**
	 * 读bean里的属性值
	 * 
	 * @param pd
	 * @param o
	 * @return
	 * @throws Exception
	 */
	public static Object getbeanvalue(PropertyDescriptor pd, Object o)
			throws Exception {

		return pd.getReadMethod().invoke(o, new Object[] {});
	}

	/**
	 * 往bean里写属性值
	 * 
	 * @param pd
	 * @param o
	 *            需要修改的bean.class
	 * @param value
	 *            值
	 * @return
	 * @throws Exception
	 */
	public static Object setbeanvalue(PropertyDescriptor pd, Object o,
			Object value) throws Exception {
		return pd.getWriteMethod().invoke(o, new Object[] { value });
	}

	/**
	 * 返回Object对象类型
	 * 
	 * @param object
	 * @return
	 */
	public static String getObjectType(Object object) {
		if (object instanceof Integer) {
			return "Integer";
		} else if (object instanceof String) {
			return "String";
		} else if (object instanceof Double || object instanceof BigDecimal) {
			return "Double";
		} else if (object instanceof Float) {
			return "Float";
		} else if (object instanceof Long) {
			return "Long";
		} else if (object instanceof Boolean) {
			return "Boolean";
		} else if (object instanceof Date) {
			return "Date";
		}
		return "Unknown";
	}

	/**
	 * 是否是可处理的类型
	 * 
	 * @param type
	 * @return
	 */
	public static boolean isTypeContains(String type) {

		type = type.toUpperCase();

		if (type.endsWith(".STRING")) {
			return true;
		} else if (type.endsWith(".INTEGER")) {
			return true;
		} else if (type.endsWith(".DOUBLE")) {
			return true;
		} else if (type.endsWith(".FLOAT")) {
			return true;
		} else if (type.endsWith(".LONG")) {
			return true;
		} else if (type.endsWith(".BOOLEAN")) {
			return true;
		} else if (type.endsWith(".DATE")) {
			return true;
		}

		return false;

	}

	public static String getClassPath(Object o) {
		return o.getClass().toString().substring(6);
	}

	@SuppressWarnings("rawtypes")
	public static List removeAssociationList(List list) {
		String name;
		PropertyDescriptor[] pds;
		Object instance;
		try {

			for (int l = 0; l < list.size(); l++) {
				instance = list.get(l);

				pds = getPropertyDescriptor(instance);

				for (int i = 0; i < pds.length; i++) {
					PropertyDescriptor pd = pds[i];
					name = pd.getName();

					if (name.equals("class")) {
						continue;
					} else if (isTypeContains(pd.getPropertyType().getName())) {
						continue;
					}
					setbeanvalue(pd, instance, null);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	/**
	 * 把Map里的数据同步到Model中
	 * 
	 * @param model
	 * @param property
	 * @return
	 */
	public static Object synInstanceData(Object model,
			Map<String, String> property) {
		PropertyDescriptor[] pds = null;
		try {
			pds = getPropertyDescriptor(model);
			String name;
			String value;
			for (int i = 0; i < pds.length; i++) {
				PropertyDescriptor pd = pds[i];
				name = pd.getName();
				value = property.get(name);
				if (value != null) {
					if (value.length() > 0) {
						setbeanvalue(pd, model, value);
					}
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return model;
	}

	/**
	 * 获得Bean里面所有属性名称
	 * 
	 * @param model
	 * @return
	 */
	public static Map<String, String> getBeanPropName(Object model) {

		Map<String, String> map = new HashMap<String, String>();

		PropertyDescriptor[] pds = null;
		try {
			pds = getPropertyDescriptor(model);
			String name;
			for (int i = 0; i < pds.length; i++) {
				PropertyDescriptor pd = pds[i];

				name = pd.getName();
				if (name.equals("class")) {
					continue;
				}
				map.put(pd.getName(), null);
			}

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

		return map;
	}

}
